#pragma once
/**
  * Reference counting smart pointer
  */
template <typename T> class smart_ptr
{
private:
	struct _proxy;
	_proxy* obj;
	void Ref()
	{
		if (obj)
			obj->refCount++;
	}
	void UnRef()
	{
		if (obj)
		{
			if (--(obj->refCount) == 0)
				delete obj;
		}
	}
public:
	/**
	  * Create null pointer
	  */
	smart_ptr()
	{
		obj = 0;				
	}

	/**
	  * Create new pointer to <code>*t</code> object with one reference
	  * \param t pointer to object
	  */
	smart_ptr(T* const t)
	{
		if (t)
			obj = new _proxy(t);
		else
			obj = 0;
	}

	/**
	  * Create pointer from existing smart pointer <code>t</code>.
	  * \param t smart pointer to object
	  */
	smart_ptr(const smart_ptr<T>& t)
	{
		obj = t.obj;
		Ref();
	}

	smart_ptr<T>& operator = (const smart_ptr<T>& t)
	{
		if (obj != t.obj)
		{
			UnRef();
			obj = t.obj;
			Ref();
		}
		return *this;
	}

	T& operator * () const
	{
		return *(obj->ref);
	}
	
	T* operator -> () const
	{
		return (obj->ref);
	}
	operator T* ()
	{
		if (obj)
			return (obj->ref);
		else
			return 0;
	}

};

template<typename T> struct smart_ptr<T>::_proxy 
{
	T* ref;
	int refCount;

	_proxy(T* const t)
	{
		ref = t;
		refCount = 1;	
	}
	~_proxy()
	{
		delete ref;
	}
};	
